package rpcserver

import (
	"encoding/json"
	"fmt"
	"gitee.com/jamon/espoir_go/common"
	"gitee.com/jamon/espoir_go/global"
	"gitee.com/jamon/espoir_go/logger"
	"gitee.com/jamon/espoir_go/route"
	"gitee.com/jamon/espoir_go/service"
)

// 主动消息处理，如push消息，节点间消息等

type PushHandler struct {
	nodeData   *global.NodeData
	serviceMgr *service.Manager
	routeCtl   *route.Controller
	sessionMgr *global.SessionManager
}

func NewPushHandler() (handler *PushHandler, err error) {
	handler = &PushHandler{
		nodeData:   global.GetNodeData(),
		serviceMgr: service.GetManager(),
		routeCtl:   route.GetController(),
		sessionMgr: global.GetSessionManager(),
	}
	return
}

func (handler *PushHandler) HandleMsg(req common.PushMsgRequest, res *common.MsgResponse) (err error) {
	if req.Type != common.MsgType_PUSH {
		err = fmt.Errorf("unknown msg type: %v", req.Type)
		return
	}

	err = handler.handlePush(&req, res)
	return
}

func (handler *PushHandler) handlePush(req *common.PushMsgRequest, res *common.MsgResponse) (err error) {
	if handler.nodeData.GetCurNodeType() != common.NodeType_Proxy {
		// 只有proxy节点才能处理push消息
		logger.Error("handlePush: only proxy node can handle push",
			logger.Kwargs{"node_type": handler.nodeData.GetCurNodeType()})
		return fmt.Errorf("only proxy node can handle push")
	}

	// 使推送消息结构和请求返回给客户端的Response结构一致
	data, err := json.Marshal(&common.Response{
		Code: common.MsgCode_SUCCESS,
		Data: req.Data,
	})
	if err != nil {
		return
	}
	msgToClient := &common.MsgResponse{
		MsgId: req.MsgId,
		Type:  common.MsgType_PUSH,
		Data:  data,
	}
	if req.IsAll {
		// 发送往该proxy上所有客户端
		err := handler.sessionMgr.Broadcast(msgToClient)
		if err != nil {
			return err
		}
	} else {
		// 发送往指定客户端
		for _, sessionID := range req.SessionIDs {
			err := handler.sessionMgr.SendMsg(sessionID, msgToClient)
			if err != nil {
				return err
			}
		}
	}
	return
}
